<?php
namespace App\Services;

use App\Api\Models\StorageBatchModel;
use App\V3\Api\Services\ShelfService;
use App\Models\CheckModel;
use App\Models\LogInstorageModel;
use App\Models\MaterielTypeModel;
use App\Models\StorageModel;
use App\Models\MaterielModel;
use App\Models\StorageManageModel;
use App\Models\TallyModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\MaterielContentModel;
use App\Models\SupplierCustomerModel;
use App\Models\MaterielPayHistoryModel;
use App\Models\MaterielOtherChargesModel;
use App\V3\Api\Models\MaterielSerialNumberModel;

class MaterielService
{
    static public function add($data)
    {
        DB::beginTransaction();

        try {
            $materielContent = json_decode($data['materiel_content'], true);
            unset($data['materiel_content']);

            //原金额(税前应付)
            $data['original_money'] = 0;
            foreach($materielContent as $value)
            {
                $data['original_money'] += $value['unit_price'] * $value['num'];
            }

            //应付金额(修改价格或折扣优惠前金额)
            $data['real_money'] = $data['original_money'] + ($data['original_money'] * ($data['tax_rate'] / 100));

            /**
             * @preferential_way:优惠方式;0:无;1:修改价格;2:折扣优惠;
             * 优惠方式为非0值时，实付金额为修改后的金额或折扣优惠后的金额
             */
            switch($data['preferential_way']) {
                case 0:
                        $data['final_money'] = $data['real_money'];
                    break;
                case 1:
                        $data['final_money'] = $data['preferential_money'];
                    break;
                case 2:
                    if($data['preferential_money'] >= 100) {
                        return ['code' => 0, 'msg' => '折扣比例不能超出百分百', 'data' => ''];
                    }
                    //折扣后
                    $afterDiscount = ($data['original_money'] * ($data['preferential_money'] / 100));
                    //税后
                    $afterTaxRate = $afterDiscount + ($afterDiscount * ($data['tax_rate'] / 100));
                    $data['final_money'] = ceil($afterTaxRate * 100) / 100;//物料均价
                    $data['discount'] = $data['preferential_money'];
                    break;
            }

            unset($data['preferential_money']);

            $time = empty($data['purchase_time'])?date('Y-d-m H:i:s'):$data['purchase_time'];
            $data['remark'] = empty($data['remark'])?'':$data['remark'];
            $data['purchase_time'] = strtotime($time);
            $data['purchase_date'] = strtotime(date('Y-m-d', strtotime($time)));
            $data['created_at'] = time();

            $supplierInfo = SupplierCustomerModel::where('id', $data['supplier_customer_id'])->first();
            $data['supplier_customer_id'] = $supplierInfo['id'];
            $data['deliver_person'] = $supplierInfo['name'];
            $data['deliver_phone'] = $supplierInfo['phone'];
            $data['deliver_address'] = $supplierInfo['address'];
            $data['supplier_name'] = $supplierInfo['name'];

            foreach($materielContent as $k => $v) {
                $storageInfo = StorageModel::where('id', $v['storage_id'])
                                            ->where('main_id', $data['main_id'])
                                            ->where('delete_flag', 0)
                                            ->first();

                if(empty($storageInfo)) {
                    return ['code' => 0, 'msg' => '仓库不存在', 'data' => ''];
                }

                $materielTypeInfo = MaterielTypeModel::where('id', $v['type_id'])->first();

                $materielContent[$k]['materiel_name'] = $materielTypeInfo['materiel_name'];
                $materielContent[$k]['type_name'] = $materielTypeInfo['type_name'];
                $materielContent[$k]['materiel_img'] = $materielTypeInfo['materiel_img'];
                $materielContent[$k]['materiel_no'] = $materielTypeInfo['materiel_no'];
                $materielContent[$k]['storage_name'] = $storageInfo['storage_name'];
                $materielContent[$k]['storage_address'] = $storageInfo['storage_address'];
            }

            $insertId = MaterielModel::insertGetId($data);
            CheckModel::insert([
                'type' => 3,
                'all_id' => $insertId,
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'status' => 0,
                'out_in_status' => 0,
                'order_no' => $data['purchase_no'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'created_at' => time(),
            ]);

            SELF::addMaterielContent($materielContent, $insertId, $data['user_id'], $data['main_id'], $data['purchase_time']);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ['id' => $insertId]];
            //其他金额累加到实付和应付内
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('创建采购:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //添加套餐内容
    static public function addMaterielContent($materielContent, $materielId, $userId, $parentId, $purchaseTime)
    {
        foreach($materielContent as &$value) {
            if(empty($value['type_id'])) {
                throw new \Exception('请选择物料产品');
            }

            if(empty($value['materiel_name'])) {
                throw new \Exception('物料名称缺失');
            }

//            if(empty($value['type_name'])) {
//                throw new \Exception('物料型号缺失');
//            }

            if(empty($value['storage_id'])) {
                throw new \Exception('请选择入库目标仓库');
            }

//            if(empty($value['unit_price'])) {
//                throw new \Exception('请填写物料单价');
//            }

            if($value['unit_price'] < 0) {
                throw new \Exception('物料单价只能为正数');
            }

            if($value['num'] < 0) {
                throw new \Exception('采购数量只能为整数');
            }

            $value['materiel_id'] = $materielId;
            $value['purchase_time'] = $purchaseTime;
            $value['user_id'] = $userId;
            $value['main_id'] = $parentId;
            $value['rest_num'] = $value['num'];
            //没有传货架库位，使用默认货架库位
            if(empty($value['shelf_id']) || empty($value['location_id'])){
                $sfData = ShelfService::get_default($value['storage_id']);

                if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                }else{
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id']=0;
                    $value['location_id']=0;
                }
            }else{
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

        }

        MaterielContentModel::insert($materielContent);

        return true;
    }

    static public function edit($data)
    {
        $data['fact_money'] = isset($data['fact_money'])?$data['fact_money']:0;

        $materielContent = json_decode($data['materiel_content'], true);
        unset($data['materiel_content']);

        $data['purchase_time'] = empty($data['purchase_time'])?time():strtotime($data['purchase_time']);

        $newMaterielTypeId = [];//新采购单内容物料id
        $data['original_money'] = 0;//税前应付应付金额
        foreach($materielContent as $value) {
            $newMaterielTypeId[] = $value['type_id'];

            $data['original_money'] += $value['num'] * $value['unit_price'];
        }

        foreach($materielContent as $k => $v) {
            $storageInfo = StorageModel::where('id', $v['storage_id'])
                ->where('main_id', $data['main_id'])
                ->where('delete_flag', 0)
                ->first();

            if(empty($storageInfo)) {
                return ['code' => 0, 'msg' => '仓库不存在', 'data' => ''];
            }

            //不传默认使用默认库位
            if(empty($v['shelf_id']) || empty($v['location_id'])){
                $sfData = ShelfService::get_default($v['storage_id']);
                if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                }else{
                    $shelf_id = 0;
                    $location_id = 0;
                    $v['shelf_id']=0;
                    $v['location_id']=0;
                }

                $materielContent[$k]['shelf_id'] = $shelf_id;
                $materielContent[$k]['location_id'] = $location_id;
            }

            $materielContent[$k]['storage_name'] = $storageInfo['storage_name'];
            $materielContent[$k]['storage_address'] = $storageInfo['storage_address'];
        }

        //应付金额(税后)
        $data['real_money'] = $data['tax_rate'] == 0?$data['original_money']:$data['original_money'] * ($data['tax_rate'] / 100) + $data['original_money'];
        /**
         * @preferential_way:优惠方式;0:无;1:修改价格;2:折扣优惠;
         * 优惠方式为非0值时，实付金额为修改后的金额或折扣优惠后的金额
         */
        switch($data['preferential_way']) {
            case 0:
                $data['final_money'] = $data['real_money'];
                break;
            case 1:
                $data['final_money'] = $data['preferential_money'];
                break;
            case 2:
                if($data['preferential_money'] >= 100) {
                    return ['code' => 0, 'msg' => '折扣比例不能超出百分百', 'data' => ''];
                }
                //折扣后
                $afterDiscount = ($data['original_money'] * ($data['preferential_money'] / 100));
                //税后
                $afterTaxRate = $afterDiscount + ($afterDiscount * ($data['tax_rate'] / 100));
                $data['final_money'] = ceil($afterTaxRate * 100) / 100;//物料均价
                $data['discount'] = $data['preferential_money'];
                break;
        }

        unset($data['preferential_money']);

        $materielContentInfo = MaterielContentModel::where('materiel_id', $data['id'])->get()->toArray();

        $uselessContentId = [];//修改后无用的采购内容id
        $needsToUpdate = [];
        $existMaterielContentTypeId = [];
        foreach($materielContentInfo as $kk => $val) {
            //已有采购内容发生替换
            if(!in_array($val['type_id'], $newMaterielTypeId)) {
                $uselessContentId[] = $val['id'];
            }
            else {
                $existMaterielContentTypeId[] = $val['type_id'];
                $v['purchase_time'] = $data['purchase_time'];

                foreach($materielContent as $k3 => $v3) {
                    if($val['type_id'] == $v3['type_id']) {
                        $v3['id'] = $val['id'];
                        $v3['materiel_id'] = $data['id'];
                        $v3['user_id'] = $data['user_id'];
                        $v3['main_id'] = $data['main_id'];
                        $v3['created_at'] = time();
                        $v3['rest_num'] = $v3['num'];
                        $v3['purchase_time'] = $data['purchase_time'];
                        $needsToUpdate[$k3] = $v3;
                    }
                }
            }
        }

        $needsToInsert = [];
        foreach($materielContent as $k => $v) {
            if(!in_array($v['type_id'], $existMaterielContentTypeId)) {
                $v['materiel_id'] = $data['id'];
                $v['user_id'] = $data['user_id'];
                $v['main_id'] = $data['main_id'];
                $v['created_at'] = time();
                $v['rest_num'] = $v['num'];
                $v['purchase_time'] = $data['purchase_time'];
                $needsToInsert[] = $v;
            }
        }

        unset($data['main_id']);
        unset($data['user_id']);

        $supplierInfo = SupplierCustomerModel::where('id', $data['supplier_customer_id'])->first();
        $data['supplier_customer_id'] = $supplierInfo['id'];
        $data['deliver_person'] = empty($data['deliver_person'])?$supplierInfo['name']:$data['deliver_person'];
        $data['deliver_phone'] = empty($data['deliver_phone'])?$supplierInfo['phone']:$data['deliver_phone'];
        $data['deliver_address'] = empty($data['deliver_address'])?$supplierInfo['address']:$data['deliver_address'];
        $data['supplier_name'] = $supplierInfo['name'];

        $materielInfo = MaterielModel::where('id', $data['id'])->first();

        if($materielInfo['pay_status'] != 0) {
            unset($data['fact_money']);
        }

        DB::beginTransaction();

        try {
            //删除无用采购内容
            MaterielContentModel::whereIn('id', $uselessContentId)->delete();
            MaterielModel::where('id', $data['id'])->update($data);
            MaterielContentModel::insert($needsToInsert);
            foreach($needsToUpdate as $k2 => $v2) {
                $v2['purchase_time'] = $data['purchase_time'];
                $v2['rest_num'] = $v2['num'];
                MaterielContentModel::where('id', $v2['id'])->lockForUpdate()->update($v2);
            }
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('修改采购单:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(),'data' => ''];
        }
    }

    //删除指定采购
    static public function del($data)
    {
        $materielInfo = MaterielModel::where('id', $data['id'])->first();

        if($materielInfo['pay_status'] == 1 || $materielInfo['in_storage_status'] == 1) {
            return ['code' => 1, 'msg' => '无法删除，请检查此采购单状态', 'data' => ''];
        }

        MaterielModel::where('id', $data['id'])->update(['delete_flag' => 1]);
        CheckModel::where('type', 3)->where('all_id', $data['id'])->update(['repeal_status' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    //添加采购但其他费用
    static public function addCharges($data)
    {
        //开启事务
        DB::beginTransaction();
        try{
            MaterielOtherChargesModel::insert($data);
            $model = MaterielModel::where('id',$data['materiel_id'])->first();
            $model->final_money += $data['money'];
            $model->other_charges = $model->other_charges+$data['money'];
            $model->save();

            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }catch (Exception $e){
            DB::rollBack();//事务回滚
            //异常响应
            Log::debug('添加其他费用:'.var_export($e->getMessage(), true));
        }
    }

    //编辑其他费用
    static public function editCharges($data)
    {
        //开启事务
        DB::beginTransaction();
        try{
            $beforeModel = MaterielOtherChargesModel::where('id',$data['id'])->first();
            MaterielOtherChargesModel::where('id',$data['id'])->update($data);
            $beforeMoney = $beforeModel['money'];
            $final = $data['money'] - $beforeMoney;
            $model = MaterielModel::where('id',$beforeModel['materiel_id'])->first();
            $model->final_money += $final;
            $model->other_charges = $model->other_charges+$final;
            $model->save();
            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }catch (Exception $e){
            DB::rollBack();//事务回滚
            //异常响应
            Log::debug('编辑其他费用:'.var_export($e->getMessage(), true));
        }
    }

    //付款
    static public function payMaterielMoney($data)
    {
        unset($data['status']);
        $materielInfo = MaterielModel::where('id',$data['materiel_id'])->first();//销售单信息
        $paidMomey = MaterielPayHistoryModel::where('materiel_id',$data['materiel_id'])->sum('money');//已收款金额

        $payInfo = MaterielPayHistoryModel::where('materiel_id',$data['materiel_id'])->first();

        if($materielInfo['pay_status'] == 2) {
            return ['0' => 0, 'msg' => '支付已完成，无需重复支付', 'data' => ''];
        }

        //支付后实付金额
        $afterPayMoney = sprintf('%.6f', ($paidMomey + $data['money']));

        if($afterPayMoney > $materielInfo['final_money']) {
            return ['code' => 1, 'msg' => '超出实际应付金额，请重试', 'data' => ''];
        }

        $payStatus = 1;
        if($afterPayMoney == $materielInfo['final_money']) {
            $payStatus = 2;
        }

        DB::beginTransaction();

        try {
            if(empty($payInfo)) {
                MaterielModel::where('id', $data['materiel_id'])
                    ->update([
                        'fact_money' => 0
                    ]);
            }

            TallyModel::insert([
                'tally_class_name' => '采购',
                'type' => 1,
                'money' => $data['money'],
                'order_no' => $materielInfo['purchase_no'],
                'main_id' => $data['main_id'],
                'add_time' => strtotime($materielInfo['purchase_time']),
                'created_at' => time()
            ]);

            MaterielModel::where('id', $data['materiel_id'])->increment('fact_money', $data['money'], [
                'pay_status' => $payStatus
            ]);

            MaterielPayHistoryModel::insert($data);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('采购付款异常:'.$e->getMessage());
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function payAll($data, $materielInfo, $paidMomey)
    {
        $data['money'] = $materielInfo['final_money'] - $paidMomey;
        MaterielModel::where('id', $data['materiel_id'])->update([
            'pay_status' => 2,
            'fact_money' => $materielInfo['final_money']
        ]);

        $materielInfo = MaterielModel::where('id', $data['materiel_id'])->first();

        unset($data['status']);
        MaterielPayHistoryModel::insert($data);
        TallyModel::insert([
            'tally_class_name' => '采购',
            'type' => 1,
            'money' => $data['money'],
            'order_no' => $materielInfo['purchase_no'],
            'main_id' => $data['main_id'],
            'add_time' => strtotime($materielInfo['purchase_time']),
            'created_at' => time()
        ]);
        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static private function payApart($data, $materielInfo, $paidMomey)
    {
        $unpaidMoney = $materielInfo['final_money'] - $paidMomey;

        if($unpaidMoney == $data['money']) {
            MaterielModel::where('id', $data['materiel_id'])->update([
                'pay_status' => 2,
                'fact_money' => $materielInfo['final_money']
            ]);
        }
        else if($unpaidMoney < $data['money']) {
            return ['code' => 1, 'msg' => '当前支付金额超出剩余应付金额', 'data' => ''];
        }
        else if($unpaidMoney > $data['money']) {
            MaterielModel::where('id', $data['materiel_id'])->increment('fact_money', $data['money']);
            MaterielModel::where('id', $data['materiel_id'])->update(['pay_status' => 1]);
        }

        $materielInfo = MaterielModel::where('id', $data['materiel_id'])->first();

        unset($data['status']);
        TallyModel::insert([
            'tally_class_name' => '采购',
            'type' => 1,
            'money' => $data['money'],
            'order_no' => $materielInfo['purchase_no'],
            'main_id' => $data['main_id'],
            'add_time' => strtotime($materielInfo['purchase_time']),
            'created_at' => time()
        ]);
        MaterielPayHistoryModel::insert($data);
        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    //采购列表
    static public function list($userId, $parentId, $data)
    {
        $query = MaterielModel::select(
                                'a.id',
                                'repeal_status',
                                'purchase_time',
                                'supplier_name',
                                'final_money',
                                'out_order_no',
                                'purchase_no',
                                'username',
                                'nickname'
                            )
                            ->from('materiel as a')
                            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
                            ->with('materielContent', function($query) {
                                $query->select(
                                    'materiel_content.id',
                                    'materiel_id',
                                    'unit_price',
                                    'num',
                                    'rest_num',
                                    'a.materiel_name',
                                    'a.type_name',
                                    'a.materiel_no',
                                    'a.materiel_img',
                                )
                                ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_content.type_id');
                            })
                            ->where('repeal_status', $data['repeal_status'])
                            ->where('a.delete_flag', 0);

        if($userId == $parentId) {
            $query->where('main_id', $parentId);
        }
        else {
            $query->where('user_id', $userId)
            ->where('main_id', $parentId);
        }

        $data = $query->orderBy('id', 'desc')
                ->paginate($data['pageSize'],['*'], '',$data['currentPage']);

        $id = [];
        foreach($data as $value) {
            $id[] = $value['id'];
        }

        $result = MaterielContentModel::select('id', 'materiel_id', 'num')->whereIn('materiel_id', $id)->get()->toArray();

        $arr = [];
        foreach($result as $ke => $val) {
            foreach($data as $k =>$v) {
                $total  = 0;
                if($val['materiel_id'] == $v['id']) {
                    $total += $val['num'];
                }
                $data[$k]['total'] += $total;
            }
        }

        return $data;
    }

    //撤销采购
    static public function cancel($mainId, $data)
    {
        $checkMaterielInfo = MaterielModel::where([
            'id' => $data['id'],
            'delete_flag' => 0
        ])->first();

        if($checkMaterielInfo['repeal_status']) {
            return ['code' => 1, 'msg' => '该采购单已撤销，无法重复操作', 'data' => ''];
        }

        if(empty($checkMaterielInfo)) {
            return ['code' => 1, 'msg' => '该采购单已被删除', 'data' => ''];
        }

        $logInfo = LogInstorageModel::where([
            'all_id_type' => 3,
            'all_id' => $data['id'],
            'is_cancel' => 0
        ])->get()->toArray();

        DB::beginTransaction();

        try {
            if(!empty($logInfo)) {
                foreach($logInfo as $value) {
                    $storageManageInfo = StorageManageModel::select(
                        'a.id',
                        'in_storage_num',
                        'b.materiel_name',
                        'b.type_name'
                    )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                    ->where('a.id', $value['curr_storage_manage_id'])->first();

                    if($storageManageInfo['delete_flag']) {
                        return ['code' => 1, 'msg' => '商品：'.$storageManageInfo['materiel_name'].'-'.$storageManageInfo['type_name'].'已被删除，无法完成撤销', 'data' => ''];
                    }

                    if($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                        return [
                           'code' => 1,
                           'msg' => '商品：'.$storageManageInfo['materiel_name'].'-'.$storageManageInfo['type_name'].'库存数不足(当前库存:'.$storageManageInfo['in_storage_num'].',操作数量:'.$value['operate_num'].')，无法完成撤销',
                           'data' => ''];
                    }

                    if(!empty($value['batch_id'])) {
                        $batchInfo = StorageBatchModel::where('id', $value['batch_id'])->first();

                        if($value['operate_num'] < $batchInfo['batch_left_num']) {
                            throw new \Exception($storageManageInfo['materiel_name'].'批次数量不足，无法完成出库，无法完成撤销');
                        }
                    }

                    StorageManageModel::where('id', $value['curr_storage_manage_id'])->decrement('in_storage_num', $value['operate_num']);
                }

                $logInfoId = [];
                foreach($logInfo as $val) {
                    $logInfoId[] = $val['id'];
                }

                LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
            }

            MaterielModel::where('id', $data['id'])->update(['repeal_status' => 1]);
            MaterielContentModel::where('materiel_id', $data['id'])->update(['repeal_status' => 1]);
            CheckModel::where([
                'type' => 3,
                'all_id' => $data['id']
            ])->update(['repeal_status' => 1]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('采购撤销异常'.var_export($e->getMessage(), true));
        }
    }

    //重新下单
    static public function addAgain($userId, $parentId, $data)
    {
        $materielInfo = MaterielModel::where('id', $data['id'])->first()->toArray();
        $materielContentInfo = MaterielContentModel::where('materiel_id', $data['id'])->get()->toArray();

        unset($materielInfo['id']);
        $materielInfo['purchase_no'] = $data['purchase_no'];
        $materielInfo['repeal_status'] = 0;
        $materielInfo['user_id'] = $userId;
        $materielInfo['main_id'] = $parentId;
        $materielInfo['created_at'] = time();
        $materielInfo['updated_at'] = NULL;
        $materielInfo['remark'] = '';
        $materielInfo['pay_status'] = 0;
        $materielInfo['in_storage_status'] = 0;
        $materielInfo['purchase_time'] = time();
        $materielInfo['purchase_date'] = strtotime(date('Y-m-d', strtotime($materielInfo['purchase_time'])));

        DB::beginTransaction();

        try {
            $insertId = MaterielModel::insertGetId($materielInfo);

            foreach($materielContentInfo as $k => $v) {
                unset($materielContentInfo[$k]['id']);
                unset($materielContentInfo[$k]['updated_at']);

                $materielContentInfo[$k]['materiel_id'] = $insertId;
                $materielContentInfo[$k]['rest_num'] = $v['num'];
                $materielContentInfo[$k]['user_id'] = $userId;
                $materielContentInfo[$k]['main_id'] = $parentId;
                $materielContentInfo[$k]['created_at'] = time();
            }

            CheckModel::insert([
                'type' => 3,
                'all_id' => $insertId,
                'main_id' => $parentId,
                'user_id' => $userId,
                'status' => 0,
                'out_in_status' => 0,
                'created_at' => time(),
                'order_no' => $data['purchase_no']
            ]);

            MaterielContentModel::insert($materielContentInfo);
            DB::commit();
            return '';
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('采购重新下单:'.var_export($e->getMessage(), true));
        }
    }

    //详细
    static public function detail($datas)
    {

        $data = MaterielModel::select(
                                'a.*',
                                'b.nickname',
                                'b.username',
                            )
                            ->with('materielContent', function($query) {
                                $query->select(
                                    'materiel_content.id',
                                    'materiel_content.type_id',
                                    'materiel_id',
                                    'unit_price',
                                    'num',
                                    'materiel_content.rest_num',
                                    'a.materiel_name',
                                    'a.type_name',
                                    'a.materiel_no',
                                    'a.materiel_img',
                                    'materiel_content.storage_id',
                                    'b.storage_name',
                                    'b.storage_address',
                                    'a.is_use_serial',
                                    'materiel_content.shelf_id',
                                    'materiel_content.location_id',
                                    's.shelf_name',
                                    'l.location_name',
                                )
                                ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_content.type_id')
                                ->leftJoin('storage as b', 'b.id', '=', 'materiel_content.storage_id')
                                ->leftJoin('storage_shelf as s','materiel_content.shelf_id','=','s.id')
                                ->leftJoin('storage_shelf_location as l','materiel_content.location_id','=','l.id');
//                                ->leftJoin('storage_manage as c', 'c.id', '=', 'materiel_content.storage_manage_id');
                            })
                            ->from('materiel as a')
                            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
                            ->where('a.id', $datas['id'])
                            ->where('a.delete_flag', 0)
                            ->orderBy('a.id', 'desc')
                            ->get()->toArray();

        foreach($data as $key => $value) {
                foreach($value['materiel_content'] as $k => $val) {
                    $data[$key]['materiel_content'][$k]['in_num'] = $val['num'] - $val['rest_num'];
                    $data[$key]['materiel_content'][$k]['is_in'] = $val['num'] == $val['rest_num']?0:1;

                    if($val['is_use_serial'] == 1){
                        $snCondition['type_id']=$val['type_id'];
                        $snCondition['materiel_content_id']=$val['id'];

                        $list = MaterielSerialNumberModel::select('serial_no')->where($snCondition)->get()->toArray();
                        $data[$key]['materiel_content'][$k]['serial_number_list']=[];

                        if(!empty($list)){

                            $str="";
                            foreach($list as $v){
                                $str .= $v['serial_no'].',';
                            }
                            $str = substr($str,0,strrpos($str,","));

                            $data[$key]['materiel_content'][$k]['serial_number_list'] = explode(',', $str);
                        }
                }
            }
        }
        return empty($data[0])?[]:$data[0];
    }

    //采购入库
    static public function materielInStorage($data)
    {
        $content = json_decode($data['content'], true);

        //采购单基础信息
        $materielInfo = MaterielModel::where('id', $content[0]['materiel_id'])->first();

        if($materielInfo['repeal_status']) {
            return ['0' => 1, 'msg' => '采购单已撤销，无法重复操作', 'data' => ''];
        }

        if($materielInfo['in_storage_status'] == 2) {
            return ['0' => 1, 'msg' => '已全部入库，无法重复操作', 'data' => ''];
        }

        //status:入库状态：2-全部 1-部分
        switch($data['status']) {
            case 1:
                $result = SELF::partInStorage($data, $content, $materielInfo);
                break;
            case 2:
                $result = SELF::partAllStorage($data, $content, $materielInfo);
                break;
        }

        return $result;
    }

    static public function partInStorage($data, $content, $materielInfo)
    {
        $newStorageArr = [];//库存中不存在商品信息
        $existStorageArr = [];//库存中已存在商品信息
        $materielSerialNumberArr=[];//采购单序列号信息
        foreach($content as $value) {
            $materielContentInfo = MaterielContentModel::select(
                'a.id',
                'a.type_id',
                'a.rest_num',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.id as second_class_id',
                'c.class_name as second_class_name',
                'c.class_no as second_class_no',
                'd.id as first_class_id',
                'd.class_name as first_class_name',
                'e.purchase_no'
            )
                ->from('materiel_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel as e', 'e.id', '=', 'a.materiel_id')
                ->where('a.id', $value['materiel_content_id'])
                ->first();

            $storageInfo = StorageModel::where('id', $value['storage_id'])->first();

            if(empty($storageInfo) || $storageInfo['delete_flag'] == 1) {
                return ['code' => 1, 'msg' => '仓库不存在,无法入库', 'data' => ''];
            }

            if($materielContentInfo['rest_num'] < $value['num']) {
                return [
                    'code' => 1,
                    'msg' => '商品:'.$materielContentInfo['materiel_name'].'-'.$materielContentInfo['type_name'].'可入库数量不足,无法完成入库,当前可操作数量:('.$materielContentInfo['rest_num'].')',
                    'data' => ''
                ];
            }

            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielContentInfo['second_class_id'],
                'type_id' => $materielContentInfo['type_id'],
                'storage_id' => $value['storage_id'],
                'main_id' => $data['main_id'],
            ])->first();

            if(empty($storageManageInfo)) {
                $newStorageArr[] = [
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'materiel_mean_cost' => $value['price'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'remark' => empty($value['remark'])?'':$value['remark'],
                    'main_id' => $data['main_id'],
                ];
            }
            else {
                $meanPirce = sprintf("%.2f",
                    (
                        ($storageManageInfo['materiel_mean_cost'] * $storageManageInfo['in_storage_num'])
                        +
                        ($value['num'] * $value['price'])
                    )
                    /
                    ($storageManageInfo['in_storage_num'] + $value['num']));

                $existStorageArr[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'in_storage_num' => $value['num'],
                    'materiel_mean_cost' => $meanPirce,
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'remark' => empty($value['remark'])?'':$value['remark'],
                    'created_at' => time(),
                    'curr_storage_num' => $storageManageInfo['in_storage_num'],
                ];
            }


        }

        DB::beginTransaction();

        try {
            $existLogInfo = [];
            if(!empty($existStorageArr)) {
                foreach($existStorageArr as $existVal) {
                    StorageManageModel::where('id', $existVal['storage_manage_id'])->increment('in_storage_num', $existVal['in_storage_num'],
                        [
                            'materiel_mean_cost' => $existVal['materiel_mean_cost'],
                            'delete_flag' => 0
                        ]
                    );

                    MaterielTypeModel::where('id', $existVal['type_id'])
                        ->update(['cost' => $existVal['materiel_mean_cost']]);

                    MaterielContentModel::where('id', $existVal['materiel_content_id'])->decrement('rest_num', $existVal['in_storage_num']);

                    $existLogInfo[] = [
                        'type' => 0,
                        'storage_id' => $existVal['storage_id'],
                        'storage_name' => $existVal['storage_name'],
                        'storage_address' => $existVal['storage_address'],
                        'curr_storage_manage_id' => $existVal['storage_manage_id'],
                        'materiel_class_id' => $existVal['materiel_class_id'],
                        'materiel_class_name' => $existVal['materiel_class_name'],
                        'materiel_class_no' => $existVal['materiel_class_no'],
                        'materiel_type_id' => $existVal['type_id'],
                        'materiel_name' => $existVal['materiel_name'],
                        'type_name' => $existVal['type_name'],
                        'materiel_no' => $existVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $existVal['in_storage_num'],
                        'last_storage_num' => $existVal['curr_storage_num'],
                        'next_storage_num' => $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                        'materiel_mean_cost' => $existVal['materiel_mean_cost'],
                        'remark' => empty($existVal['remark'])?'':$existVal['remark'],
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ];

                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $existVal['materiel_name'],
                        $existVal['type_name'],
                        $existVal['storage_id'],
                        $existVal['storage_name'],
                        $data,
                        $existVal['in_storage_num'],
                        $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                    );
                }
            }

            $newLogInfo = [];
            if(!empty($newStorageArr)) {
                foreach($newStorageArr as $newVal) {
                    $newId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'in_storage_num' => $newVal['in_storage_num'],
                        'main_id' => $newVal['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ]);

                    //同步成本至物料商品
                    MaterielTypeModel::where('id', $newVal['type_id'])
                        ->update(['cost' => $newVal['materiel_mean_cost']]);

                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $newVal['materiel_name'],
                        $newVal['type_name'],
                        $newVal['storage_id'],
                        $newVal['storage_name'],
                        $data,
                        $newVal['in_storage_num'],
                        $newVal['in_storage_num'],
                    );

                    MaterielContentModel::where('id', $newVal['materiel_content_id'])->decrement('rest_num', $newVal['in_storage_num']);

                    $newLogInfo[] = [
                        'type' => 0,
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'curr_storage_manage_id' => $newId,
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'materiel_type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $newVal['in_storage_num'],
                        'last_storage_num' => 0,
                        'next_storage_num' => $newVal['in_storage_num'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'remark' => empty($newVal['remark'])?'':$newVal['remark'],
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ];
                }
            }

            if(!empty($newLogInfo)) {
                LogInstorageModel::insert($newLogInfo);
            }

            if(!empty($existLogInfo)) {
                LogInstorageModel::insert($existLogInfo);
            }

            $checkRestNum = MaterielContentModel::where('materiel_id', $materielInfo['id'])
                ->where('rest_num', '!=', 0)->get()->toArray();

            if(empty($checkRestNum)) {
                $status = 2;
                CheckModel::where([
                    'type' => 3,
                    'all_id' => $materielInfo['id'],
                    'main_id' => $data['main_id']
                ])->update([
                    'status' => 1,
                    'out_in_status' => 0
                ]);
            }
            else {
                $status = 1;

                CheckModel::where([
                    'type' => 3,
                    'all_id' => $materielInfo['id'],
                    'main_id' => $data['main_id']
                ])->update([
                    'out_in_status' => 1
                ]);
            }

            MaterielModel::where('id', $materielInfo['id'])->update(['in_storage_status' => $status]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('部分采购入库异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function partAllStorage($data, $content, $materielInfo)
    {
        $newStorageArr = [];//库存中不存在商品信息
        $existStorageArr = [];//库存中已存在商品信息
        $materielSerialNumberArr=[];//采购单序列号信息
        foreach($content as $value) {
            $materielContentInfo = MaterielContentModel::select(
                'a.id',
                'a.type_id',
                'a.rest_num',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.id as second_class_id',
                'c.class_name as second_class_name',
                'c.class_no as second_class_no',
                'd.id as first_class_id',
                'd.class_name as first_class_name',
                'e.purchase_no'
            )
                ->from('materiel_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel as e', 'e.id', '=', 'a.materiel_id')
                ->where('a.id', $value['materiel_content_id'])
                ->first();
            $storageInfo = StorageModel::where('id', $value['storage_id'])->first();

            if(empty($storageInfo) || $storageInfo['delete_flag'] == 1) {
                return ['code' => 1, 'msg' => '仓库不存在,无法入库', 'data' => ''];
            }

            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielContentInfo['second_class_id'],
                'type_id' => $materielContentInfo['type_id'],
                'storage_id' => $value['storage_id'],
                'main_id' => $data['main_id'],
            ])->first();

            if(empty($storageManageInfo) || $storageManageInfo['delete_flag'] == 1) {
                $newStorageArr[] = [
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'materiel_mean_cost' => $value['price'],
                    'remark' => $value['remark'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $materielContentInfo['rest_num'],
                    'main_id' => $data['main_id'],
                ];
            }
            else {
                $meanPirce = sprintf("%.2f",
                    (
                        ($storageManageInfo['materiel_mean_cost'] * $storageManageInfo['in_storage_num'])
                        +
                        ($materielContentInfo['num'] * $value['price'])
                    )
                    /
                    ($storageManageInfo['in_storage_num'] + $materielContentInfo['rest_num']));

                $existStorageArr[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'materiel_mean_cost' => $meanPirce,
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $materielContentInfo['rest_num'],
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'created_at' => time(),
                    'curr_storage_num' => $storageManageInfo['in_storage_num'],
                ];
            }
        }

        DB::beginTransaction();

        try {
            $existLogInfo = [];
            if(!empty($existStorageArr)) {
                foreach($existStorageArr as $existVal) {
                    StorageManageModel::where('id', $existVal['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + '.$existVal['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + '.$existVal['in_storage_num']),
                            'materiel_mean_cost' => $existVal['materiel_mean_cost']
                        ]);

                    //同步成本至物料商品
                    MaterielTypeModel::where('id', $existVal['type_id'])
                        ->update(['cost' => $existVal['materiel_mean_cost']]);

                    MaterielContentModel::where('id', $existVal['materiel_content_id'])->decrement('rest_num', $existVal['in_storage_num']);

                    $existLogInfo[] = [
                        'type' => 0,
                        'storage_id' => $existVal['storage_id'],
                        'storage_name' => $existVal['storage_name'],
                        'storage_address' => $existVal['storage_address'],
                        'curr_storage_manage_id' => $existVal['storage_manage_id'],
                        'materiel_class_id' => $existVal['materiel_class_id'],
                        'materiel_class_name' => $existVal['materiel_class_name'],
                        'materiel_class_no' => $existVal['materiel_class_no'],
                        'materiel_type_id' => $existVal['type_id'],
                        'materiel_name' => $existVal['materiel_name'],
                        'type_name' => $existVal['type_name'],
                        'materiel_no' => $existVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $existVal['in_storage_num'],
                        'last_storage_num' => $existVal['curr_storage_num'],
                        'next_storage_num' => $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                        'materiel_mean_cost' => $existVal['materiel_mean_cost'],
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ];

                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $existVal['materiel_name'],
                        $existVal['type_name'],
                        $existVal['storage_id'],
                        $existVal['storage_name'],
                        $data,
                        $existVal['in_storage_num'],
                        $existVal['in_storage_num'],
                    );
                }
            }

            $newLogInfo = [];
            if(!empty($newStorageArr)) {
                foreach($newStorageArr as $newVal) {
                    $newId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'in_storage_num' => $newVal['in_storage_num'],
                        'main_id' => $newVal['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ]);

                    //同步成本至物料商品
                    MaterielTypeModel::where('id', $newVal['type_id'])
                        ->update(['cost' => $newVal['materiel_mean_cost']]);

                    MaterielContentModel::where('id', $newVal['materiel_content_id'])->decrement('rest_num', $newVal['in_storage_num']);

                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $newVal['materiel_name'],
                        $newVal['type_name'],
                        $newVal['storage_id'],
                        $newVal['storage_name'],
                        $data,
                        $newVal['in_storage_num'],
                        $newVal['in_storage_num'],
                    );

                    $newLogInfo[] = [
                        'type' => 0,
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'curr_storage_manage_id' => $newId,
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'materiel_type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $newVal['in_storage_num'],
                        'last_storage_num' => 0,
                        'next_storage_num' => $newVal['in_storage_num'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ];
                }
            }

            if(!empty($newLogInfo)) {
                LogInstorageModel::insert($newLogInfo);
            }

            if(!empty($existLogInfo)) {
                LogInstorageModel::insert($existLogInfo);
            }

            MaterielModel::where('id', $materielInfo['id'])->update(['in_storage_status' => 2]);

            CheckModel::where([
                'type' => 3,
                'all_id' => $materielInfo['id'],
                'main_id' => $data['main_id']
            ])->update([
                'status' => 1,
                'out_in_status' => 0
            ]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('部分采购入库异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * @入库-数据组装
     * @created 在 2021/11/27 17:17 创建
     * @param Request $request
     * @return array
     * @author: Sun Wu
     */
    static private function prepareInstorage($data, $content, $materielContentInfo, $materielId)
    {
        $updateInStorageNum = [];//已存在物料入库信息
        $newStorageManageInfo = [];//采购单入库信息
        $logInStorage = [];//入库操作记录
        $contentNumInfo = [];//采购单内物料数量信息
        foreach($materielContentInfo as $key => $value) {
            /**
             * @param $inStorageNum 实际入库数量
             * @param $value['in_num'] 部分物料入库数量(部分入库时使用)
             * @param $value['rest_num'] 采购单内物料剩余入库数量(全部入库时使用)
             */
            $inStorageNum = $data['status'] == 1?$value['in_num']:$value['rest_num'];

            $contentNumInfo[] = [
                'id' => $value['id'],//采购单主键id
                'rest_num' => $inStorageNum,//剩余数量
            ];

            //检查库存信息
            $checkStorageManage = StorageManageModel::where([
                'type_id' => $value['type_id'],
                'materiel_name' => $value['materiel_name'],
                'type_name' => $value['type_name'],
                'storage_id' => $value['storage_id'],
                'storage_name' => $value['storage_name'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->first();

            $storageInfo = StorageModel::where('id', $value['storage_id'])
                                        ->where('main_id', $data['main_id'])
                                        ->where('delete_flag', 0)
                                        ->first();

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '入库目标仓库不存在', 'data' => ''];
            }

            $meanPirce = 0;
            if(empty($checkStorageManage)) {
                $meanPirce = $value['unit_price'];
                //采购单入库信息
                $newStorageManageInfo[] = [
                    'first_class' => $value['first_class'],
                    'materiel_content_id' => $value['id'],//物料内容id
                    'materiel_class_id' => $value['class_id'],//物料二级分类id
                    'materiel_class_name' => $value['class_name'],//物料二级分类名称
                    'materiel_class_no' => empty($value['class_no'])?'':$value['class_no'],//物料二级分类名称
                    'type_id' => $value['type_id'],//物料id
                    'materiel_name' => $value['materiel_name'],//物料名称
                    'type_name' => $value['type_name'],//物料型号名称
                    'materiel_no' => empty($value['materiel_no'])?'':$value['materiel_no'],//物料编号
                    'materiel_mean_cost' => $value['unit_price'],
                    'storage_id' => $storageInfo['id'],//仓库id
                    'storage_name' => $storageInfo['storage_name'],//仓库名
                    'storage_address' => $storageInfo['storage_address'],//仓库地址
                    'in_storage_num' => $inStorageNum,//采购单内物料商品入库数量
                    'main_id' => $data['main_id'],//主账号id
                    'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                    'created_at' => time(),
                ];
            }
            else {
                $meanPirce = sprintf("%.2f",
                    (
                        ($checkStorageManage['materiel_mean_cost'] * $checkStorageManage['in_storage_num'])
                        +
                        ($inStorageNum * $value['unit_price'])
                    )
                    /
                    ($checkStorageManage['in_storage_num'] + $inStorageNum));

                $updateInStorageNum[] = [
                    'id' => $checkStorageManage->id,
                    'in_storage_num' => $inStorageNum,
                    'materiel_mean_cost' => $meanPirce
                ];
            }

            //入库操作记录
            $logInStorage[] = [
                'type' => 0,//日志类型;0:入库;1:调拨入库;2:直接入库;
                'purchase_no' => $value['purchase_no'],
                'storage_id' => $value['storage_id'],//入库目标仓库id
                'storage_name' => $value['storage_name'],//仓库名
                'storage_address' => $value['storage_address'],//仓库地址
                'last_storage_id' => 0,//调拨前所在仓库id
                'materiel_class_id' => $value['class_id'],//物料二级分类id
                'materiel_class_name' => $value['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($value['class_no'])?'':$value['class_no'],//物料二级分类名称
                'materiel_type_id' => $value['type_id'],//物料id
                'materiel_name' => $value['materiel_name'],//物料名称
                'type_name' => $value['type_name'],//物料型号名称
                'materiel_no' => empty($value['materiel_no'])?'':$value['materiel_no'],//物料编号
                'operate_num' => $inStorageNum,//操作数量
                'last_storage_num' => empty($checkStorageManage['in_storage_num'])?0:$checkStorageManage['in_storage_num'],//操作前库存数
                'next_storage_num' => $checkStorageManage['in_storage_num'] + $inStorageNum,//操作后库存数
                'materiel_mean_cost' => $meanPirce,//物料均价
                'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                'remark' => empty($data['remark'])?'':$data['remark'],//备注
                'all_id_type' => 3,//单据类型;0:无;1:报溢;2:退货;3:采购;
                'all_id' => $value['materiel_id'],//单据id
                'user_id' => $data['user_id'],//操作人id
                'main_id' => $data['main_id'],//主账号id
                'created_at' => time()
            ];
        }

        return SELF::inStorage($updateInStorageNum, $newStorageManageInfo, $logInStorage, $contentNumInfo, $data, $content, $materielId);
    }

    /**
     * @入库
     * @created 在 2021/11/29 10:19 创建
     * @param $updateInStorageNum 库存中已有物料入库
     * @param $newStorageManageInfo 新物料入库
     * @param $logInStorage 入库操作日志
     * @param $contentNumInfo 采购单内物料数量信息
     * @return array
     * @author:Sun Wu
     */
    static public function inStorage($updateInStorageNum, $newStorageManageInfo, $logInStorage, $contentNumInfo, $data, $content, $materielId)
    {
        DB::beginTransaction();

        try {
            //库存中存在与入库物料相同物料时，更新库存数
            if(!empty($updateInStorageNum)) {
                foreach($updateInStorageNum as $k => $v) {
                    if($v['in_storage_num'] > 0) {
                        StorageManageModel::where('id', $v['id'])
                            ->update([
                                'in_storage_num' => DB::raw('in_storage_num + '.$v['in_storage_num']),
                                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$v['in_storage_num']),
                                'materiel_mean_cost' => $v['materiel_mean_cost']
                            ]);
                    }
                }
            }

            //库存中不存在与入库物料相同物料时，新增库存
            if(!empty($newStorageManageInfo)) {
                foreach($newStorageManageInfo as $value) {
                    $newStorageManageInfo[] = [
                        'first_class' => $value['first_class'],
                        'materiel_content_id' => $value['id'],//物料内容id
                        'materiel_class_id' => $value['class_id'],//物料二级分类id
                        'materiel_class_name' => $value['class_name'],//物料二级分类名称
                        'materiel_class_no' => empty($value['class_no'])?'':$value['class_no'],//物料二级分类名称
                        'type_id' => $value['type_id'],//物料id
                        'materiel_name' => $value['materiel_name'],//物料名称
                        'type_name' => $value['type_name'],//物料型号名称
                        'materiel_no' => empty($value['materiel_no'])?'':$value['materiel_no'],//物料编号
                        'materiel_mean_cost' => $value['unit_price'],
                        'storage_id' => $value['id'],//仓库id
                        'storage_name' => $value['storage_name'],//仓库名
                        'storage_address' => $value['storage_address'],//仓库地址
                        'in_storage_num' => $value['in_storage_num'],//采购单内物料商品入库数量
                        'main_id' => $data['main_id'],//主账号id
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'created_at' => time(),
                    ];

                    $materielContentId = $value['materiel_content_id'];
                    unset($value['materiel_content_id']);
                    unset($value['first_class']);
                    $newId = StorageManageModel::insertGetId($value);
                    MaterielContentModel::where('id', $materielContentId)->update(['storage_manage_id' => $newId]);
                    unset($materielContentId);
                }
            }

            //扣除采购单内物料采购数量
            foreach($contentNumInfo as $value) {
                MaterielContentModel::where('id', $value['id'])
                    ->lockForUpdate()
                    ->decrement('rest_num', $value['rest_num']);
            }

            $contentInfo = MaterielContentModel::where([
                'materiel_id' => $materielId,
            ])->where('rest_num', '!=', 0)->get()->toArray();

            if(empty($contentInfo)) {
                $status = 2;
                CheckModel::where([
                    'type' => 3,
                    'all_id' => $materielId
                ])->update(['status' => 1]);
            }
            else {
                $status = 1;
            }

            MaterielModel::where('id', $materielId)->update(['in_storage_status' => $status]);

            //创建入库操作记录
            LogInstorageModel::insert($logInStorage);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            DB::rollback();
            Log::debug('入库：'.var_export($e->getMessage(), true));
        }
    }

    //修改采购单内商品采购单价
    static public function editUnitPrice($data)
    {
        $materielContentInfo = MaterielContentModel::where('id', $data['id'])->first();
        $materielInfo = MaterielModel::where('id', $materielContentInfo['materiel_id'])->first();

        if($materielInfo['in_storage_status'] != 0) {
            return ['code' => 1, 'msg' => '当前采购单入库状态已改变，无法对商品单价进行修改', 'data' => ""];
        }

        MaterielContentModel::where('id', $data['id'])->update(['unit_price' => $data['unit_price']]);
        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }
}
